SCSI 共享盘实现方案

您所在的位置:网站首页 red hat virtio scsi disk SCSI 共享盘实现方案

SCSI 共享盘实现方案

2023-04-14 22:21| 来源: 网络整理| 查看: 265

最近因为工作需要,调研了部分公有云厂商 SCSI 共享盘的功能和用法。SCSI 共享盘对于一些集群使用场景是非常有用的,但是网络上对虚拟机使用 SCSI 共享盘这块介绍很多都比较零散,所以摸索了一些背后可能的实现方式,总结了这篇文章。废话不多说,下面开始介绍。

一、功能简介

SCSI 类型共享云硬盘是一种支持多台云主机并发读写操作的数据块级存储设备。通过 Lun 卷的 SCSI 锁机制,即 SCSI Reservation 命令来进行 SCSI 锁的操作。如果某台主机给磁盘传输了一条SCSI Reservation 命令,则这个磁盘对于其他的主机就处于锁定状态。该机制有效避免了多台云主机同时操作磁盘时对磁盘数据造成破坏。

SCSI-3 Reservation(Persistent Reservation)是使用 PR Key 来对设备进行加锁。一台 Host 会有唯一的 PR Key,不同的 host,PR Key 也不同。所以使用该机制,需要将多台云主机分散到不同的物理计算节点上,否则 SCSI 锁无法生效。

另外,共享云硬盘为云主机提供共享访问块设备的能力,但该共享功能的实现还需要结合搭建集群或者搭建共享文件系统来使用。否则如果没有集群管理能力,文件系统之间无法做到数据同步,磁盘会遭到破坏。另外,一旦共享云硬盘已经被格式化成某种文件系统,不可再挂载到其他不同操作系统的云主机,否则文件系统格式不兼容,也可能会对磁盘造成破坏。

因此,使用 SCSI 云硬盘,需要注意的是:

共享云硬盘只支持数据盘。使用共享云硬盘的主机需要分散到不同的计算节点上。共享云硬盘同时只能为一种操作系统使用,不可在不同操作系统(Linux 和 Windows)之间进行交替使用。共享云硬盘需要结合高可用集群或者共享文件系统使用。二、原理简介使用 SCSI 共享云硬盘,需要虚拟机配置使用 virtio-scsi 驱动。

虚机中的 virtio_scsi 驱动将 SCSI 命令入 VirtQueue 队列。然后由 qemu 中模拟的 virtio-scsi 设备的 IO 线程将 SCSI 命令出队并处理,最终该 SCSI 命令透传与否取决于存储后端类型以及 qemu 的配置选项。

(1)如果存储后端不支持 SCSI 命令,则透传也无用,所有的 SG_IO 都会失败,所以 libvirt 只允许少数几种类型的存储后端配置成 LUN 访问模式。

(2) qemu 的配置选项

如果将 SCSI 硬盘配置成普通硬盘模式 。则 SCSI 读写命令会转成 libiscsi 的调用,一些非读写命令则会由 qemu target 填充实际配置参数或模拟数据返回。如果将 SCSI 硬盘配置成 LUN 模式,即 。只有少数几个SCSI 命令由 qemu target 填充实际配置的参数或模拟数据返回外,其它 SCSI 命令都会通过 libiscsi 进行透传。

2. 在实现虚拟机群集时,通常要求虚拟机发送持久保留 SCSI 命令。但是,操作系统限制将这些命令发送到非特权程序,因为使用不当会破坏存储结构的正常运行。所以 SCSI 共享盘最主要是需要解决该问题。以下内容也均为从这一方面着手,解决该问题。

三、虚拟机配置3.1 方案一:sgio 配置 unfiltered

虚拟机使用以下方案实现共享云硬盘,需要满足以下前提条件。

计算节点需要有 sg (SCSI generic driver) 内核模块,且支持 unpriv_sgio。虚拟机磁盘使用 virtio-scsi 驱动,且磁盘格式为真实的整块 raw 格式磁盘。创建虚拟机时支持配置虚拟机组,使得使用同一块共享盘的多个虚拟机所在的宿主机,具有反亲和性。

在计算节点 CVK 上为多链路的 lun 卷配置好 multipath,将 multipath 路径透传给虚拟机。如果虚拟机需要使用盘的 persistent reservation,即 SCSI 锁功能,必须配置 sgio='unfiltered',来允许 SG_IO ioctl 命令被 libiscsi 透传。

sgio 必须配置成 unfiltered,才能允许 SG_IO ioctl 命令将 persistent reservation 透传给客户虚拟机。除了需要设置 sgio='unfiltered',还需要设置 实现在多台客户虚拟机中实现共享 Lun 卷。device='lun' 与 device='disk' 基本相同。不同点在于设置成 lun 时,来自虚拟机的通用 SCSI 指令可以被宿主机内核接收并传递给物理设备。设置 device='lun' 时,磁盘必须是真实的 raw 设备,否则,内核会拒绝来自虚拟机的通用 SCSI 指令,这样就等同于配置 device='disk'。3.2 方案二:network 连接 iscsi

虚拟机使用以下方案实现共享云硬盘,需要满足以下前提条件。

libvirt version >= 4.7.0。libvirt 从 4.7.0 开始支持配置 initiator iqn name。该配置与虚拟机本身的 name 区别开,否则 iscsi 盘会读取虚拟机名字作为 iqn,导致认证失败。qemu version >= 2.12.0,且编译 qemu 时,需要 enable libiscsi,否则通过 network 连接 iscsi 盘时,qemu 无法识别 iscsi 协议。虚拟机磁盘使用 virtio-scsi 驱动,且磁盘格式为真实的整块 raw 格式磁盘。创建虚拟机时支持配置虚拟机组,使得使用同一块共享盘的多个虚拟机所在的宿主机,具有反亲和性。

通过 network 方式连接 iscsi 盘。由于对虚拟机磁盘设置 type='network',且 protocol='iscsi' 时,host 字段只能配置一个存储控制器的主机信息。所以使用这种方案实现共享盘时,虚拟机需要对一块共享盘配置多个disk xml 来透传多链路的单个 lun 卷。这种方案不需要内核支持 unpriv_sgio。但是单个 lun 卷共享盘的多路径需要在虚拟机内部安装 multipathd 服务来自动配置,且可以由用户控制。

2.2 方案三:使用 libvirt 的 reservations

虚拟机使用以下方案实现共享云硬盘,需要满足以下前提条件。

libvirt version >= 4.4.0。虚拟机磁盘使用 virtio-scsi 驱动,且磁盘格式为真实的整块 raw 格式磁盘。创建虚拟机时支持配置虚拟机组,使得使用同一块共享盘的多个虚拟机所在的宿主机,具有反亲和性。

libvirt 从 4.4.0 版本开始支持配置 reservations。配置该 element 可以为基于 SCSI 类型的磁盘开启 persistent reservations。该 element 必须配置 managed 属性,这个属性可选值为 yes 和 no。当配置为 yes 时,由 libvirt 来准备并管理需要的资源。配置为 no 时,由 hypervisor 充当客户端,并提供服务的 unix socket 路径。

qemu 有个 persistent reservation manager,它将通过 Unix 套接字将命令转发到外部特权帮助程序。帮助程序仅允许将 persistent reservations 命令发送到 QEMU 具有文件描述符的设备,因此QEMU除非可以访问套接字和设备,否则将无法进行持久保留。

配置 managed='yes',由 libvirt 来实现:

配置 managed='no',需要启动 qemu-pr-helper 服务,并将 qemu-pr-helper 的 unix socket path 配给虚拟机的 scsi 盘。qemu 2.12.0 版本已经提供了这个功能。启动 qemu-pr-helper 服务:

# qemu-pr-helper -d --socket=/var/run/qemu-pr-helper.sock

配置虚拟机磁盘:

四、验证4.1 搭建基于 iSCSI 的 RHCS 集群

以下测试内容是在两台标准 CentOS7.6 计算节点上做的测试验证,通过 targetcli 创建的 iSCSI 设备进行模拟。

详细搭建过程这里不具体描述。以下是搭建结果:

[root@client ~]# pcs status Cluster name: testcluster Stack: corosync Current DC: client (version 1.1.21-4.el7-f14e36fd43) - partition with quorum Last updated: Tue Jun 2 10:57:46 2020 Last change: Tue Jun 2 10:56:44 2020 by root via cibadmin on client 2 nodes configured 7 resources configured Online: [ client server ] Full list of resources: scsi-shooter (stonith:fence_scsi): Started client Clone Set: dlm-clone [dlm] Started: [ client server ] Clone Set: clvmd-clone [clvmd] Started: [ client server ] Clone Set: clusterfs-clone [clusterfs] Started: [ client server ] Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled

集群搭建完成后,两台机器自动挂载共享盘到指定目录。

[root@client ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos7-root 40G 1.4G 39G 4% / devtmpfs 476M 0 476M 0% /dev tmpfs 488M 76M 413M 16% /dev/shm tmpfs 488M 7.2M 481M 2% /run tmpfs 488M 0 488M 0% /sys/fs/cgroup /dev/sda2 197M 120M 77M 61% /boot tmpfs 98M 0 98M 0% /run/user/0 /dev/mapper/cluter_vg-cluster_lv 2.0G 35M 2.0G 2% /mnt/testgfs [root@server ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos7-root 40G 1.4G 39G 4% / devtmpfs 476M 0 476M 0% /dev tmpfs 488M 61M 428M 13% /dev/shm tmpfs 488M 7.2M 480M 2% /run tmpfs 488M 0 488M 0% /sys/fs/cgroup /dev/sda2 197M 120M 77M 61% /boot tmpfs 98M 0 98M 0% /run/user/0 /dev/mapper/cluter_vg-cluster_lv 2.0G 35M 2.0G 2% /mnt/testgfs4.2 共享盘验证

虚拟机 server 和 client 分别被创建到了不同的宿主机,可以看到有两个 PR Key 被注册。

[root@server ~]# sg_persist -k /dev/sdb LIO-ORG test_fileio 4.0 Peripheral device type: disk PR generation=0x5, 2 registered reservation keys follow: 0xe1f90000 0xe1f90001 [root@client ~]# sg_persist -k /dev/sdb LIO-ORG test_fileio 4.0 Peripheral device type: disk PR generation=0x4, 2 registered reservation keys follow: 0xe1f90000 0xe1f90001

查看 Persistent Reservation 类型,默认为 Write Exclusive, registrants only,该类型表示所有注册者均可进行写入操作,且只有一个PRs持有者。

[root@server testgfs]# sg_persist -r /dev/sdb LIO-ORG test_fileio 4.0 Peripheral device type: disk PR generation=0x7, Reservation follows: Key=0xe1f90000 scope: LU_SCOPE, type: Write Exclusive, registrants only

在 server 端和 client 端同时操作一个文件,代码如下:

[root@server ~]# cat timestemp.py import time file_name="/mnt/testgfs/test-ecs1" while True: with open(file_name, "a+") as file_obj: now = time.strftime("%Y-%m-%d %H-%M-%S from server", time.localtime(time.time())) file_obj.write(now+"\n") time.sleep(0.5) [root@client ~]# cat timestemp.py import time file_name="/mnt/testgfs/test-ecs1" while True: with open(file_name, "a+") as file_obj: now = time.strftime("%Y-%m-%d %H-%M-%S from client", time.localtime(time.time())) file_obj.write(now+"\n") time.sleep(0.5)

在两台虚拟机上同时执行 timestemp.py,查看结果 /mnt/testgfs/test-ecs1 如下,可以看到数据均有被写入,且两台虚拟机上看到的 /mnt/testgfs/test-ecs1 文件内容一致。

[root@client ~]# cat /mnt/testgfs/test-ecs1 2020-06-02 11-37-30 from server 2020-06-02 11-37-30 from client 2020-06-02 11-37-30 from server 2020-06-02 11-37-30 from client 2020-06-02 11-37-31 from server 2020-06-02 11-37-31 from client 2020-06-02 11-37-31 from server 2020-06-02 11-37-31 from client 2020-06-02 11-37-32 from server 2020-06-02 11-37-32 from client 2020-06-02 11-37-32 from server 2020-06-02 11-37-32 from client 2020-06-02 11-37-33 from server 2020-06-02 11-37-33 from client 2020-06-02 11-37-33 from server 2020-06-02 11-37-33 from client ......五、参考华为 SCSI 产品https://libvirt.org/formatdomain.htmlhttps://runsisi.com/2019-01-07/virtio-scsi-ceph-rbd https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/virtualization_deployment_and_administration_guide/storage_vols


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3